using System.Collections.Generic;
using System.Text;

namespace NFreeMarker.Core
{
    /**
     * An instruction representing a switch-case structure.
     */
    public sealed class SwitchBlock : TemplateElement // NOTE: Was internal
    {
        private Case _defaultCase;
        private readonly Expression _testExpression;

        /**
         * @param testExpression the expression to be tested.
         */

        internal SwitchBlock(Expression testExpression)
        {
            _testExpression = testExpression;
            NestedElements = new List<TemplateElement>();
        }

        /**
         * @param cas a Case element.
         */
        internal void AddCase(Case cas)
        {
            if (cas.IsDefault)
            {
                _defaultCase = cas;
            }
            NestedElements.Add(cas);
        }

        internal override void Accept(Environment env)
        {
            bool processedCase = false;
            try
            {
                foreach (Case cas in NestedElements)
                {
                    bool processCase = false;

                    // Fall through if a previous case tested true.
                    if (processedCase)
                    {
                        processCase = true;
                    }
                    else if (!cas.IsDefault)
                    {
                        // Otherwise, if this case isn't the default, test it.
                        var equalsOp = new ComparisonExpression(_testExpression, cas.Expression, "==");
                        processCase = equalsOp.IsTrue(env);
                    }
                    if (processCase)
                    {
                        env.Visit(cas);
                        processedCase = true;
                    }
                }

                // If we didn't process any nestedElements, and we have a default,
                // process it.
                if (!processedCase && _defaultCase != null)
                {
                    env.Visit(_defaultCase);
                }
            }
            catch (BreakInstruction.Break)
            {
            }
        }

        public override string GetCanonicalForm()
        {
            var buf = new StringBuilder("<#switch ");
            buf.Append(_testExpression.GetCanonicalForm());
            buf.Append(">");
            foreach (Case cas in NestedElements)
            {
                buf.Append(cas.GetCanonicalForm());
            }
            if (_defaultCase != null)
            {
                buf.Append(_defaultCase.GetCanonicalForm());
            }
            buf.Append("</#switch>");
            return buf.ToString();
        }

        public override string GetDescription()
        {
            return "switch " + _testExpression;
        }
    }
}